// Copyright (c) 2011 SameGoal LLC.
// All Rights Reserved.
// Author: Andy Hochhaus <ahochhaus@samegoal.com>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "net/http/server/comet/request_helper.h"

#include <fcntl.h>
#include <gflags/gflags.h>
#include <glog/logging.h>

#include <map>
#include <string>
#include <vector>

#include "base/string.h"
#include "net/http/server/comet/json.h"

namespace sg {
namespace net {
namespace http {
namespace server {
namespace comet {

RequestHelper::RequestHelper(es::Request *req) : req_(req) {
}

bool RequestHelper::StartChunk(const PaddingType padding) {
  req_->StartChunk(es::OK);
  if (padding == SCRIPT) {
    std::string domain;
    std::string payload = "<html><body>";
    if (req_->GetQueryParam("DOMAIN", &domain) && !domain.empty()) {
      payload += "<script>try{document.domain='" + domain +
          "';}catch(e){}</script>\n";
    }
    if (!SendChunk(payload, NONE)) {
      return false;
    }
  }
  return true;
}

bool RequestHelper::SendChunk(const std::string &body,
                              const PaddingType padding) {
  std::string buf;
  if (!FillPaddedBuffer(body, padding, &buf)) {
    return false;
  }
  req_->SendChunk(buf);
  return true;
}

bool RequestHelper::EndChunk(const PaddingType padding) {
  std::string last_chunk;
  if (padding == SCRIPT) {
    last_chunk = "<script>try{parent.d();}catch(e){}</script>\n";
  }
  req_->EndChunk(last_chunk);
  return true;
}

bool RequestHelper::Send(const es::HttpStatus status_code,
                         const std::string &body,
                         const PaddingType padding) {
  std::string payload;
  if (!FillPaddedBuffer(body, padding, &payload)) {
    return false;
  }
  req_->Send(status_code, payload);
  return true;
}

bool RequestHelper::FillPaddedBuffer(const std::string &body,
                                     const PaddingType padding,
                                     std::string *buf) {
  std::vector<std::string> payload_vector;
  if (padding == LENGTH) {
    int64 utf8_len = sg::string::Utf8Length(body);
    if (utf8_len < 0) {
      LOG(ERROR) << "Illegal UTF8 encoding: " << body
                 << " using raw string length instead: " << body.length();
      utf8_len = body.length();
    }
    payload_vector.push_back(sg::string::ToString(utf8_len));
    payload_vector.push_back("\n");
    payload_vector.push_back(body);
  } else if (padding == SCRIPT) {
    payload_vector.push_back("<script>try{parent.m(");
    payload_vector.push_back(JsonString(body, true).Serialize());
    payload_vector.push_back(")}catch(e){}</script>\n");
  } else {
    payload_vector.push_back(body);
  }
  sg::string::Join("", payload_vector, buf);
  return true;
}

}  // namespace comet
}  // namespace server
}  // namespace http
}  // namespace net
}  // namespace sg
